﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCmd;
using System.Net.Sockets;
using System.IO;
using LitJson;
using UnityEngine;
using System.Net;

/// <summary>
/// 使用TcpClient和NetWorkStream连接服务器
/// </summary>
public class ServerInClientTcp : IServer
{
    //private string _serverIP = "192.168.22.5"
    private string _serverIP;// = "192.168.20.105";
    private int _port;// = 4096;

    private IClient _client;
    //客户端
    private TcpClient _netClient;
    private NetworkStream outStream;
    private MemoryStream memStream;

    private const int MAX_READ = 8192;
    private byte[] byteBuffer = new byte[MAX_READ];
    private Timer _reciveTimer;

    public ServerInClientTcp()
    {
        _serverIP = MiscTable.instance[1].IP;
        _port = MiscTable.instance[1].Port;

        memStream = new MemoryStream();
    }

    //只要接受导数据，就进入回调
    private void ReadComplete()
    {
        try
        {
            reciveData();
        }
        catch (Exception ex)
        {
            Debug.Log("接收数据异常，连接手动断开，" + ex.Message);
            Debug.Log("错误堆栈" + ex.StackTrace);
            //stopRecive();
            //closeServer();
        }
    }

    private void reciveData()
    {
        int len = _netClient.Available;
        if (len <= 0)
        {
            return;
        }

        //Debug.Log("收到长度：" + len);
        int receiveNumber = outStream.Read(byteBuffer, 0, len);
        OnReceive(byteBuffer, len);
    }

    /// <summary>
    /// 读数据回调
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="length"></param>
    void OnReceive(byte[] buffer, int length)
    {
        memStream.Seek(0, SeekOrigin.End);
        memStream.Write(buffer, 0, length);
        memStream.Seek(0, SeekOrigin.Begin);

        // 应用层解数据
        Package.instance.Read(memStream, _client);

        //Create a new stream with any leftover bytes
        byte[] leftover = new byte[memStream.RemainingBytes()];
        memStream.Read(leftover, 0, (int)memStream.RemainingBytes());
        memStream.SetLength(0);     //Clear
        memStream.Write(leftover, 0, leftover.Length);
    }

    /// <summary>
    /// 写数据
    /// </summary>
    void WriteMessage(byte[] message)
    {
        if (IsConnected())
        {
            outStream.BeginWrite(message, 0, message.Length, OnWrite, null);
        }
        else
        {
            Debug.LogError("链接不可用");
        }
    }
    /// <summary>
    /// 向链接写入数据流
    /// </summary>
    void OnWrite(IAsyncResult r)
    {
        try
        {
            outStream.EndWrite(r);
        }
        catch (Exception ex)
        {
            Debug.LogError("OnWrite--->>>" + ex.Message);
        }
    }
    
    #region IServer接口
    public void SendCmd(Cmd cmd)
    {
        // 仅为单机版保留接口
    }

    public void ReciveCmd(Cmd cmd)
    {
        byte[] packageBytes = Package.instance.Write(cmd);

        WriteMessage(packageBytes);
    }

    public void Connect(IClient net)
    {
        _client = net;
        if (_netClient == null)
        {
            _netClient = new TcpClient();
        }
        if (IsConnected()) { return; }

        var endPoint = new IPEndPoint(IPAddress.Parse(_serverIP), _port);
        Debug.Log("正在连接服务器：" + endPoint);
        _netClient.Connect(endPoint);
        Debug.Log("连接服务器成功~~");

        //获取流
        if (outStream != null)
        {
            outStream.Close();
        }
        outStream = _netClient.GetStream();

        //开启异步读取
        if (_reciveTimer == null)
        {
            _reciveTimer = TimerMgr.instance.CreateFrameBaseTimerAndStart(ReadComplete);
        }
    }

    public void ReciveCmdStr(Type type, string cmdStr)
    {
        // 对客户端透明，不需要在这里写
    }

    public bool IsConnected()
    {
        if (_netClient != null)
        { return _netClient.Connected; }

        return false;
    }

    public void UnConnect(IClient net)
    {
        _client = null;
        //stopRecive();
        outStream.Close();
        _netClient.Close();
    }
    #endregion IServer接口
}
